package input;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;

import main.listeners.listenerClasses.gui.ChatActivatedEvent;
import main.listeners.listenerClasses.gui.ConsoleToggleEvent;
import main.listeners.listenerClasses.gui.GUIListener;
import main.listeners.listenerClasses.gui.IngameChangedEvent;
import main.listeners.listenerClasses.gui.ScoreBoardToggleEvent;
import main.listeners.listenerClasses.gui.SpawnMenuChangedEvent;

import settings.ControlSettings;

import com.jme.input.InputHandler;
import com.jme.input.MouseInput;
import com.jme.input.controls.Binding;
import com.jme.input.controls.GameControl;
import com.jme.input.controls.GameControlManager;
import com.jme.input.controls.binding.KeyboardBinding;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.system.DisplaySystem;

import fileHandling.language.options.Controls;

/**
 * Super-class for all input-handlers that are used.
 * 
 * @author Wasserleiche
 */
public class NodeInputHandler extends InputHandler {
	
	protected static Collection<Controls> exceptions;
	
	/** The root-Node that shall be used. */
	protected Node rootNode;
	/** The {@link GameControlManager} that will be used for all {@link GameControl}s. */
	protected GameControlManager manager;
	protected HashMap<Controls, GameControl> controlMap;
	
	/**
	 * Constructs a new NodeInputHandler. Creates also a new {@link GameControlManager}.
	 * @param rootNode The root-Node that will be used.
	 */
	public NodeInputHandler(Node rootNode) {
		this.rootNode = rootNode;
		manager = new GameControlManager();
		controlMap = new HashMap<Controls, GameControl>();
		
		if(exceptions == null) {
			exceptions = new HashSet<Controls>();
			exceptions.add(Controls.Chat);
			exceptions.add(Controls.Team_Chat);
			exceptions.add(Controls.Squad_Chat);
		}
	}
	
	protected GUIListener getChatListener() {
		return new GUIListener() {
			@Override
			public void chatActivated(ChatActivatedEvent event) {
				setKeyInputsEnabled(!event.getChatState().isActive(), exceptions);
			}
			
			@Override
			public void spawnMenuChanged(SpawnMenuChangedEvent event) {}
			@Override
			public void scoreBoardToggled(ScoreBoardToggleEvent event) {}
			@Override
			public void ingameChanged(IngameChangedEvent event) {}
			@Override
			public void consoleToggled(ConsoleToggleEvent event) {}
		};
	}
	
	public Vector3f getMouseDirection() {
		MouseInput mouse = MouseInput.get();
		Vector2f screenPos = new Vector2f(mouse.getXAbsolute(), mouse.getYAbsolute());
		DisplaySystem display = DisplaySystem.getDisplaySystem();
		Vector3f worldCoords = display.getWorldCoordinates(screenPos, 0);
		Vector3f worldCoords2 = display.getWorldCoordinates(screenPos, 1);
		return worldCoords2.subtract(worldCoords).normalize();
	}
	
	protected GameControl registerKeyControl(Controls control) {
		GameControl gameControl = manager.addControl(controlMap.size() + "");
		gameControl.addBinding(getKeyBinding(control));
		
		controlMap.put(control, gameControl);
		
		return gameControl;
	}
	
	protected Binding getKeyBinding(Controls control) {
		ControlSettings settings = ControlSettings.get();
		return new KeyboardBinding(settings.getKey(settings.getValueOf(control)));
	}
	
	protected void setKeyInputsEnabled(boolean enable, Collection<Controls> exceptions) {
		for(Controls control : controlMap.keySet()) {
			if(!exceptions.contains(control)) controlMap.get(control).setEnabled(enable);
		}
	}
	
	public void changeControlSettings() {
		for(Controls control : controlMap.keySet()) {
			GameControl gameControl = controlMap.get(control);
			gameControl.clearBindings();
			gameControl.addBinding(getKeyBinding(control));
		}
	}
}